import {CloseOutlined, UserOutlined} from "@ant-design/icons";
import {Bubble, Sender} from "@ant-design/x";
import {request, useRequest} from "@umijs/max";
import {GetProps, Typography, Table} from "antd";
import React, {FC, ReactNode, useEffect, useRef, useState} from "react";
import imgPath from './fmt.webp';

export const ChatContent: FC<IChatContentProps> = ({
  style,
  callback,
  senderRef,
  onClose,
}) => {
  const [, update] = useState({});
  const {current: state} = useRef({
    loading: false,
    apiInputOpen: true,
    value: '',
    messages: [] as Exclude<GetProps<typeof Bubble.List>['items'], undefined>,
    imagePreview: {
      show: false,
      groupData: [] as TChatCallbackFixedData[],
      current: 0,
    },
  });


  const {run: chatApi} = useRequest(
    (params: {message: string}) => {
      return request('/api/chat', {
        method: 'post',
        data: params,
      });
    },
    {
      manual: true,
      // formatResult: (r) => r,
      onSuccess: async (data: Array<TChatCallbackFixedData | TChatCallbackComponentData | TUnknown>) => {
        // console.log(data.answer);
        // const data = (() => {
        //   let value;
        //   try {
        //     // console.log(JSON.parse(data.answer));
        //     value = JSON.parse(resData.answer);
        //   } catch (error) {
        //     try {
        //       let str = resData.answer as string;
        //       const startIndex = str.indexOf('```json');

        //       str = str.slice(startIndex + '```json'.length);
        //       const endIndex = str.indexOf('```');
        //       str = str.slice(0, endIndex);
        //       // console.log(JSON.parse(str));
        //       value = JSON.parse(str);
        //     } catch (error) {
        //       value = [];
        //     }
        //   }

        //   return (Array.isArray(value) ? value : [value]) as Array<TChatCallbackFixedData | TChatCallbackComponentData | TUnknown>;
        // })();

        // const sqlData = data.filter((ii) => 'id' in ii) as TChatCallbackFixedData[];
        const componentData = data.filter((ii) => 'templateType' in ii) as TChatCallbackComponentData[];
        const uData = data.filter((ii) => 'type' in ii && ii.type === 'unknown') as TUnknown[];
        const errorData = componentData.filter(ii => Array.isArray(ii.reason) && ii.reason.length);
        if (errorData.length) {
          setMessageItem('chat', getChatComponentDataNode(errorData[0]));
        }
        else {
          // if (sqlData.length) setMessageItem('chat', getChatSqlDataNode(sqlData));
          // componentData.forEach((item) => setMessageItem('chat', getChatComponentDataNode(item)));
          const allData = data.filter(ii => 'id' in ii || 'templateType' in ii) as Array<TChatCallbackFixedData | TChatCallbackComponentData>;
          if (allData.length) {
            setMessageItem('chat', getChatTableNode(allData));
          }
          else {
            const msg = uData?.[0]?.message || '没查询到任何内容';
            setMessageItem('chat', msg);
          }
        }
        state.loading = false;
        update({});
      },
      onError: () => {
        state.loading = false;
        update({});
      }
    },
  );

  const setMessageItem = (type: 'chat' | 'user', message: ReactNode) => {
    const avatarMap = {
      chat: {icon: <UserOutlined />, style: {color: '#f56a00', backgroundColor: '#fde3cf'} as React.CSSProperties},
      user: {icon: <UserOutlined />, style: {color: '#fff', backgroundColor: '#87d068', } as React.CSSProperties},
      hide: {icon: <></>, style: {visibility: 'hidden'} as React.CSSProperties},
    };
    let avatar = avatarMap[type];

    if (state.messages.at(-1)) {
      const lastItem = state.messages.at(-1);
      if (lastItem && type === lastItem.role) {
        avatar = avatarMap.hide;
      }
    }


    state.messages.push({
      content: message,
      role: type,
      avatar,
      placement: type === 'chat' ? 'start' : 'end',
    });
    state.messages = state.messages.slice();
    update({});
  };

  const getChatComponentDataNode = (data: TChatCallbackComponentData) => (
    <div>
      {
        Array.isArray(data.reason) && data.reason.length
          ? (
            <>
              <Typography.Title level={5}>完善组件: {data.templateType}</Typography.Title>
              {data.reason.map((ii, index) => <div key={ii}><Typography.Text>{index + 1}: {ii}</Typography.Text></div>)}
            </>
          )
          : (
            <div style={{display: 'flex', justifyContent: 'space-between'}}>
              <span style={{paddingRight: 8}}>{data.templateType}</span>
              <a onClick={() => callback?.(JSON.parse(JSON.stringify(data)))}>使用</a>
            </div>
          )
      }
    </div>
  );

  const getChatTableNode = (data: Array<TChatCallbackFixedData | TChatCallbackComponentData>) => (
    <Table
      columns={[
        {
          dataIndex: 'type',
          title: '类型',
          width: '5%',
          ellipsis: true,
          render: (_, record) => {
            if ('id' in record) {
              return record.type === 'Kit' ? '套件' : '模板'
            }
            else {
              return '组件'
            }
          }
        },
        {
          dataIndex: 'name',
          title: '名称',
          width: '10%',
          ellipsis: true,
          render: (_, record) => {
            if ('id' in record) {
              return <Typography.Text ellipsis type="success">{record.name}</Typography.Text>;
            }
            else {
              return <Typography.Text ellipsis type="success">{record.templateType}</Typography.Text>;
            }
          }
        },
        {
          dataIndex: 'description',
          title: '描述',
          width: '15%',
          ellipsis: true,
          render: (_, record) => {
            if ('id' in record) {
              return <Typography.Text ellipsis type="secondary">{record.description}</Typography.Text>;
            }
            else {
              return <Typography.Text ellipsis type="secondary">{JSON.stringify(record.params)}</Typography.Text>;
            }
          }
        },
        {
          dataIndex: 'action',
          title: '操作',
          width: '5%',
          ellipsis: true,
          render: (_, record) => {
            return <a onClick={() => callback?.(JSON.parse(JSON.stringify(record)))}>使用</a>
          }
        },
      ]}
      pagination={false}
      // showHeader={false}
      dataSource={data}
      size="small"
      tableLayout="fixed"
    />
  );

  useEffect(() => {
    setMessageItem('chat', 'Hello，欢迎使用IAS，你可以说：帮我建一个信息表');
  }, []);

  return (
    <div style={{...style, display: 'flex', flexDirection: 'column'}}>
      {/* <Image.PreviewGroup
        preview={{
          visible: state.imagePreview.show,
          current: state.imagePreview.current,
          onVisibleChange: (value) => {
            state.imagePreview.show = value;
            update({});
          },
          onChange: (current) => {
            state.imagePreview.current = current;
            update({});
          },
        }}
      >
        {
          state.imagePreview.groupData?.map((item, index) => (
            <Image
              key={`${item.id}-${index}`}
              width={0}
              style={{display: 'none'}}
              src={item.imageUrl}
            />
          ))
        }
      </Image.PreviewGroup> */}
      <div style={{display: 'flex', justifyContent: 'space-between', alignItems: 'center', paddingBottom: 10, marginTop: -6}}>
        <div style={{fontSize: 20, display: 'flex', alignItems: 'center', color: '#664ce8'}}>
          <div
            style={{
              width: 20,
              height: 20,
              background: `url(${imgPath}) no-repeat center`,
              backgroundSize: 'contain',
              backgroundPosition: 'bottom center',
              position: 'relative',
              top: 2,
              marginRight: 2,
            }}
          />
          IAS AI
        </div>
        <CloseOutlined style={{fontSize: 18}} onClick={onClose} />
      </div>
      <div style={{flex: 1, height: 0, overflow: 'auto', display: 'flex', flexDirection: 'column', justifyContent: 'end', padding: '6px 0'}}>
        <Bubble.List
          items={state.messages}
          autoScroll
        />
      </div>
      <Sender
        ref={senderRef}
        style={{position: 'sticky', bottom: 0, left: 0}}
        // header={(
        //   <Sender.Header
        //     open={state.apiInputOpen}
        //     title={(
        //       <Form.Item label="ApiKey" style={{margin: 0}}>
        //         <Input value={state.apiKey} onChange={(e) => {
        //           state.apiKey = e.target.value;
        //           update({});
        //         }} />
        //       </Form.Item>
        //     )}
        //     onOpenChange={(e) => {
        //       state.apiInputOpen = e;
        //       update({});
        //     }}
        //   />
        // )}
        value={state.value}
        loading={state.loading}
        readOnly={state.loading}
        onChange={(v) => {
          state.value = v;
          update({});
        }}
        onSubmit={() => {
          if (!state.value) return;
          setMessageItem('user', state.value);
          chatApi({message: state.value});
          state.loading = true;
          state.value = '';
          update({});
        }}
        onCancel={() => {
          // 中断
          // state.value = '';
          // state.loading = false;
          // update({});
        }}
      />
    </div>
  )
};

interface IChatContentProps {
  style?: React.CSSProperties;
  callback?: (data: TChatCallbackData) => void;
  show?: boolean;
  senderRef: GetProps<typeof Sender>['ref'];
  onClose?: () => void;
}

export type TChatCallbackData = TChatCallbackFixedData | TChatCallbackComponentData;

type TChatCallbackFixedData = {
  id: number,
  name: string,
  type: 'Kit' | 'Template',
  description: string,
};

type TChatCallbackComponentData = {
  templateType: string;
  componentId: string;
  params: object;
  reason: string[];
}

type TUnknown = {
  type: 'unknown';
  message: string;
}
